<script setup lang="ts" name="CkAside">
import { useDrag, useDrop } from 'vue3-dnd'
import { getEmptyImage } from 'react-dnd-html5-backend'
import { toRefs } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { useLayoutStore } from '@/store/bigScreen/layoutStore'
import { cloneDeep } from 'lodash-es'
import { getParent, findVisibleLength } from '../../../utils'

const layoutStore = useLayoutStore()

const { isLayoutDragging, isNear, isNearSelf, dropTo, dropLevel, dropIndex, dropId, currentDragModule, layout } = storeToRefs(layoutStore)

const props = defineProps({
  info: {
    type: Object,
    default: () => {
      return {}
    }
  },
  preview: {
    type: Boolean,
    default: false
  },
  index: {
    type: Number,
    default: 0
  }
})

const cardRef = ref(null)

const [, drop] = useDrop({
  accept: props.info.config.acceptDragType,
  canDrop: () => {
    return props.info.config.canDrop
  },
  hover: (item: any, monitor) => {
    if (!cardRef.value) return
    const hoverBoundingRect = cardRef.value?.getBoundingClientRect()
    const clientOffset = monitor.getClientOffset()
    if (clientOffset.y - hoverBoundingRect.top < 12 && clientOffset.y - hoverBoundingRect.top > 0 && item.config.position !== 'root' && item.config.position === props.info.config.position) {
      isNear.value = true
      isNearSelf.value = true
      dropTo.value = props.info.config.position
      dropIndex.value = -1
      dropId.value = ''
      dropLevel.value = 'aside'
    } else {
      isNear.value = false
      isNearSelf.value = false
      dropTo.value = 'root'
      dropIndex.value = -1
      dropId.value = ''
      dropLevel.value = 'aside'
    }
  },
  drop(item) {
    if (dropTo.value === 'left' || dropTo.value === 'right') {
      const res: any = cloneDeep(item)
      res.options.attr.x = 0
      res.options.attr.y = 0
      layoutStore.moveLayout(res)
    }
  }
})

const [dragCollect, drag, preview] = useDrag({
  type: props.info.config.dragType,
  item: () => {
    const res = cloneDeep(props.info)
    res.component = null
    res.index = props.index
    if (res.config.position === 'left') {
      res.parent = getParent(layout.value.left, res.id)
      res.isNearMain = true
    } else if (res.config.position === 'right') {
      res.parent = getParent(layout.value.right, res.id)
      res.isNearMain = true
    } else {
      res.parent = getParent(layout.value.root, res.id)
      res.isNearMain = false
    }
    layoutStore.setCurrentDraggingPreviewModule(res)
    return res
  },
  canDrag: () => {
    return props.info.config.canDrag
  },
  collect: (monitor) => ({
    isDragging: monitor.isDragging()
  })
})

const { isDragging } = toRefs(dragCollect)

const setRef = (el) => {
  cardRef.value = drop(el)
}

const isRootAloneDragging = () => {
  if (!props.preview && currentDragModule.value && currentDragModule.value.config.position === 'root' && currentDragModule.value.parent[currentDragModule.value.parent.length - 1] === props.info.id) {
    if (currentDragModule.value.config.dragType === 'aside') {
      return true
    } else if (currentDragModule.value.config.dragType === 'tab' || currentDragModule.value.config.dragType === 'package') {
      const dragAsideIndex = layout.value.root.findIndex((v) => v.id === currentDragModule.value.parent[currentDragModule.value.parent.length - 1])
      const dragColumnIndex = layout.value.root[dragAsideIndex].children.findIndex((v) => v.id === currentDragModule.value.parent[currentDragModule.value.parent.length - 2])
      if (findVisibleLength(layout.value.root[dragAsideIndex].children) === 1 && findVisibleLength(layout.value.root[dragAsideIndex].children[dragColumnIndex].children) === 1) {
        return true
      } else {
        return false
      }
    } else {
      const dragAsideIndex = layout.value.root.findIndex((v) => v.id === currentDragModule.value.parent[currentDragModule.value.parent.length - 1])
      const dragColumnIndex = layout.value.root[dragAsideIndex].children.findIndex((v) => v.id === currentDragModule.value.parent[currentDragModule.value.parent.length - 2])
      const dragTabIndex = layout.value.root[dragAsideIndex].children[dragColumnIndex].children.findIndex((v) => v.id === currentDragModule.value.parent[currentDragModule.value.parent.length - 3])
      if (findVisibleLength(layout.value.root[dragAsideIndex].children) === 1 && findVisibleLength(layout.value.root[dragAsideIndex].children[dragColumnIndex].children) === 1 && findVisibleLength(layout.value.root[dragAsideIndex].children[dragColumnIndex].children[dragTabIndex].children) === 1) {
        return true
      } else {
        return false
      }
    }
  } else {
    return false
  }
}

const setClass = computed(() => {
  return {
    active: isNearSelf.value,
    'is-dragging': isDragging.value,
    preview: props.preview,
    default: !props.preview,
    'is-root-alone-dragging': isRootAloneDragging(),
    'left': props.info.config.position === 'left',
    'right': props.info.config.position === 'right',
    'root': props.info.config.position === 'root'
  }
})

watch(
  () => isDragging.value,
  (value) => {
    isLayoutDragging.value = value
  }
)

onMounted(() => {
  preview(getEmptyImage(), { captureDraggingState: true })
})
</script>

<template>
  <div :ref="setRef" class="aside-container" :class="setClass">
    <div :ref="drag" class="aside-header"></div>
    <div class="aside-body">
      <template v-if="props.info.children && props.info.children.length > 0">
        <template v-for="item, index in props.info.children" :key="index">
          <template v-if="item.component && item.visible">
            <component :is="item.component" :info="item" :preview="props.preview" :index="index"></component>
          </template>
        </template>
      </template>
    </div>
  </div>
</template>

<style scoped lang="scss">
.aside-container{
  position: relative;
  display: flex;
  flex-direction: column;

  .aside-header{
    height: 13px;
    background: var(--el-bg-color-overlay);
    border: 1px solid var(--el-bg-color-page);
    border-bottom: none;
  }

  .aside-body{
    display: flex;
    flex: 1;
  }

  &.is-dragging{
    border: 1px solid var(--el-bg-color-page);

    * {
      opacity: 0;
    }

    &.active {
      &::before {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        border: 2px solid var(--el-color-primary);
        content: '';
      }
    }
  }

  &.is-root-alone-dragging{
    opacity: 0;
  }

  &.root, &.preview{

    .column+.column{
      :deep(.column-body){
        padding-left: 1px;
      }
    }
  }

  &.preview{
    &.left{
      margin-right: 0;

      .column+.column{
        margin-left: 0
      }
    }

    &.right{
      margin-left: 0;

      .column+.column{
        margin-left: 0
      }
    }
  }

  &.left{
    margin-right: 1px;

    .column+.column{
      margin-left: 1px;
    }
  }

  &.right{
    margin-left: 1px;

    .column+.column{
      margin-left: 1px;
    }
  }
}
</style>
